package Model.BD;

import org.hibernate.Session;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Transaction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.exception.ConstraintViolationException;

public class DAO<T> {

    private Session session = null;
    private Class classe;
    private List consulta;
    private Transaction tx;

    public DAO(Class classe) {
        this.session = HibernateUtil.getInstance();
        this.classe = classe;
        this.session.flush();
        tx = null;
    }

    public void salvar(T t) throws Exception {

        try {
            tx = session.beginTransaction();
            session.merge(t);
            tx.commit();

        } catch (ConstraintViolationException c) {

            throw new Exception("campos duplicados ou nulos", c);

        } catch (Exception e) {

            throw new Exception(e.getMessage(), e);

        } finally {
        }
    }

    public Integer salvarId(T t) throws Exception {

        try {
            tx = session.beginTransaction();
            t = (T) session.merge(t);
            tx.commit();

        } catch (ConstraintViolationException c) {

            throw new Exception("campos duplicados ou nulos", c);

        } catch (Exception e) {

            throw new Exception(e.getMessage(), e);

        } finally {
            return t.hashCode();
        }
    }

    public void Excluir(T t) throws Exception {

        try {
            tx = session.beginTransaction();
            session.delete(t);
            tx.commit();

        } catch (ConstraintViolationException c) {

            throw new Exception("campos duplicados ou nulos");

        } catch (Exception e) {

            throw new Exception(e.getMessage());

        } finally {
            session.close();
        }
    }

    public List<T> consultar() throws Exception {

        List lista = null;

        try {
            Criteria cri = this.session.createCriteria(this.classe);
            try {
                //cri.addOrder(Order.asc("nome"));
            } catch (Exception e) {
            } finally {
                lista = cri.list();
//                session.close();
                return lista;
            }

        } catch (NullPointerException ex) {

            throw new Exception(ex.getMessage());

        } catch (Exception e) {

            throw new Exception(e.getMessage());

        }
    }

    public List<T> consultarNotaProdutor() throws Exception {

        List lista = null;

        try {
            Criteria cri = this.session.createCriteria(this.classe);
            try {
                cri.addOrder(Order.asc("nomeProdutor"));

            } catch (Exception e) {
            } finally {
                lista = cri.list();
                session.close();
                return lista;
            }

        } catch (NullPointerException ex) {

            throw new Exception(ex.getMessage());

        } catch (Exception e) {

            throw new Exception(e.getMessage());

        }
    }

    public List<T> consultarNotaProdutorEmpresa() throws Exception {

        List lista = null;

        try {
            Criteria cri = this.session.createCriteria(this.classe);
            try {
                cri.addOrder(Order.asc("nomeEmpresa"));
            } catch (Exception e) {
            } finally {
                lista = cri.list();
                session.close();
                return lista;
            }

        } catch (NullPointerException ex) {

            throw new Exception(ex.getMessage());

        } catch (Exception e) {

            throw new Exception(e.getMessage());

        }
    }

    public List<T> consultarNotaProdutorNumNota(String campo_consultar, String valor_consultar) throws Exception {

        List lista = null;

        try {
            Criteria cri = this.session.createCriteria(this.classe);
            try {
                cri.add(Restrictions.eq(campo_consultar, valor_consultar));
                cri.addOrder(Order.asc("numNota"));
            } catch (Exception e) {
            } finally {
                lista = cri.list();
                session.close();
                return lista;
            }

        } catch (NullPointerException ex) {

            throw new Exception(ex.getMessage());

        } catch (Exception e) {

            throw new Exception(e.getMessage());

        }
    }

    public List<T> consultarNotaProdutorAno(String campo_consultar, String campo_consultar2, String valor_consultar, String valor_consultar2) throws Exception {

        List lista = null;

        try {
            Criteria cri = this.session.createCriteria(this.classe);
            try {
                cri.add(Restrictions.eq(campo_consultar, valor_consultar));
                cri.add(Restrictions.eq(campo_consultar2, valor_consultar2));
                cri.addOrder(Order.asc("ano"));
            } catch (Exception e) {
            } finally {
                lista = cri.list();
                session.close();
                return lista;
            }

        } catch (NullPointerException ex) {

            throw new Exception(ex.getMessage());

        } catch (Exception e) {

            throw new Exception(e.getMessage());

        }
    }

    public List<T> consultarNotaProdutorCPF(String campo_consultar, String campo_consultar2, String campo_consultar3, String valor_consultar, String valor_consultar2, int valor_consultar3) throws Exception {

        List lista = null;

        try {
            Criteria cri = this.session.createCriteria(this.classe);
            try {
                cri.add(Restrictions.eq(campo_consultar, valor_consultar));
                cri.add(Restrictions.eq(campo_consultar2, valor_consultar2));
                cri.add(Restrictions.eq(campo_consultar3, valor_consultar3));
                cri.addOrder(Order.asc("cpf"));
            } catch (Exception e) {
            } finally {
                lista = cri.list();
                session.close();
                return lista;
            }

        } catch (NullPointerException ex) {

            throw new Exception(ex.getMessage());

        } catch (Exception e) {

            throw new Exception(e.getMessage());

        }
    }

    public List<T> consultarNotaProdutorIncra(String campo_consultar, String campo_consultar2, String campo_consultar3, String campo_consultar4, String valor_consultar, String valor_consultar2, String valor_consultar3, int valor_consultar4) throws Exception {

        List lista = null;

        try {
            Criteria cri = this.session.createCriteria(this.classe);
            try {
                cri.add(Restrictions.eq(campo_consultar, valor_consultar));
                cri.add(Restrictions.eq(campo_consultar2, valor_consultar2));
                cri.add(Restrictions.eq(campo_consultar3, valor_consultar3));
                cri.add(Restrictions.eq(campo_consultar4, valor_consultar4));
                cri.addOrder(Order.asc("incra"));
            } catch (Exception e) {
            } finally {
                lista = cri.list();
                session.close();
                return lista;
            }

        } catch (NullPointerException ex) {

            throw new Exception(ex.getMessage());

        } catch (Exception e) {

            throw new Exception(e.getMessage());

        }
    }

    public List<T> consultarOrdenado() throws Exception {

        List lista = null;

        try {
            Criteria cri = this.session.createCriteria(this.classe);
            cri.addOrder(Order.asc("nome"));
            try {
                //cri.addOrder(Order.asc("nome"));
            } catch (Exception e) {
            } finally {
                lista = cri.list();

                session.close();
                return lista;
            }

        } catch (NullPointerException ex) {

            throw new Exception(ex.getMessage());

        } catch (Exception e) {

            throw new Exception(e.getMessage());

        }
    }

    /**
    Retorn

    a uma lista de objetos, tendo como valor de comparacao um campo que eh uma chave estrangeira na tabela
    Ex. retorna um lista de cidades se pesquisando pelo valor de cod_estado
    Chamada do metodo:
    List<Cidade> x = daof.getCidadeDAO().ConsultaComChaveEstrangeira("estado", "cod_estado", 27);
    String relacionamento = ex. para pesquisar cidades pelo cod_estado, o valor de relacionamento sera estado
     */
    public List consultaComFK(String relacionamento, String campo_consultar, int valor_consultar) throws Exception {

        List lista = null;

        try {
            this.session = HibernateUtil.getInstance();
            Criteria cri = session.createCriteria(this.classe);
            cri = cri.createCriteria(relacionamento);
            cri.add(Restrictions.eq(campo_consultar, valor_consultar));
            lista = cri.list();
        } catch (Exception e) {

            throw new Exception(e.getMessage());

        } finally {
            this.session.close();
            return lista;
        }//fim finally
    }

    public List consultaComFK2(String relacionamento, String relacionamento2, String campo_consultar, int valor_consultar) throws Exception {

        List lista = null;

        try {
            this.session = HibernateUtil.getInstance();
            Criteria cri = session.createCriteria(this.classe);
            Criteria cri2 = cri.createCriteria(relacionamento);
            cri2.createCriteria(relacionamento2);
            cri2.add(Restrictions.eq(campo_consultar, valor_consultar));
            lista = cri.list();
        } catch (Exception e) {

            throw new Exception(e.getMessage());

        } finally {
            this.session.close();
            return lista;
        }//fim finally
    }

    public List consultaComPK2(String relacionamento, String campo_consultar1, int valor_consultar1, String campo_consultar2, int valor_consultar2) throws Exception {

        List lista = null;

        try {
            this.session = HibernateUtil.getInstance();
            Criteria cri = session.createCriteria(this.classe);
            cri = cri.createCriteria(relacionamento);
            cri.add(Restrictions.eq(campo_consultar1, valor_consultar1));
            cri.add(Restrictions.eq(campo_consultar2, valor_consultar2));
            lista = cri.list();
        } catch (Exception e) {

            throw new Exception(e.getMessage());

        } finally {
            this.session.close();
            return lista;
        }//fim finally
    }

    /**
     * Retorna lista de items comforme caminho da chave composta
     * Ex: consultaComPKComposta("chaveComposta.previsao.codPrevisao", 1 );
     * */
    public List consultaComPKComposta(String caminhoCampo, Object valorConsultar) throws Exception {

        List lista = null;

        try {
            this.session = HibernateUtil.getInstance();
            Criteria criteria = session.createCriteria(this.classe);
            criteria.add(Restrictions.eq(caminhoCampo, valorConsultar));

            lista = criteria.list();

        } catch (Exception e) {

            throw new Exception(e.getMessage(), e);

        } finally {
            session.close();
            return lista;
        }
    }

    /**
     * Metodo Consultar por um campo, deve ser o mesmo nome da variável que a classe com as anotattions
     */
    public List consultarUmItem(String campo_consultar, Object valor_consultar) throws Exception {

        List lista = null;

        try {
            this.session = HibernateUtil.getInstance();
            Criteria cri = session.createCriteria(this.classe);
            cri.add(Restrictions.eq(campo_consultar, valor_consultar));
            cri.addOrder(Order.asc(campo_consultar));
            lista = cri.list();
        } catch (Exception e) {

            throw new Exception(e.getMessage());

        } finally {

            session.close();
            return lista;
        }//fim finally
    }

    public List consultarData(String campo_consultar, Object valor_consultar) throws Exception {

        List lista = null;

        try {
            this.session = HibernateUtil.getInstance();
            Criteria cri = session.createCriteria(this.classe);
            cri.add(Restrictions.eq(campo_consultar, valor_consultar));
            cri.addOrder(Order.asc(campo_consultar));
            lista = cri.list();
        } catch (Exception e) {

            throw new Exception(e.getMessage());

        } finally {

            session.close();
            return lista;
        }//fim finally
    }

    public Object consultarObjetoCodigo(String campo_consultar, Integer valor_consultar) throws Exception {

        List lista = null;

        try {
            this.session = HibernateUtil.getInstance();
            Criteria cri = session.createCriteria(this.classe);
            cri.add(Restrictions.eq(campo_consultar, valor_consultar));
            cri.addOrder(Order.asc(campo_consultar));
            lista = cri.list();
        } catch (Exception e) {

            throw new Exception(e.getMessage());

        } finally {

            session.close();
            return lista.get(0);
        }//fim finally
    }

    public List consultarDoisItens(String campo_consultar1, String campo_consultar2,
            Object valor_consultar1, Object valor_consultar2) throws Exception {
        List lista = null;
        try {

            this.session = HibernateUtil.getInstance();
            Criteria cri = session.createCriteria(this.classe);
            cri.add(Restrictions.eq(campo_consultar1, valor_consultar1));
            cri.add(Restrictions.eq(campo_consultar2, valor_consultar2));
            lista = cri.list();

        } catch (Exception e) {
        } finally {
            session.close();
            return lista;
        }//fim finally
    }

    public List consultarTresItens(String campo_consultar1, String campo_consultar2, String campo_consultar3,
            Object valor_consultar1, Object valor_consultar2, Object valor_consultar3) throws Exception {
        List lista = null;
        try {

            this.session = HibernateUtil.getInstance();
            Criteria cri = session.createCriteria(this.classe);
            cri.add(Restrictions.eq(campo_consultar1, valor_consultar1));
            cri.add(Restrictions.eq(campo_consultar2, valor_consultar2));
            cri.add(Restrictions.eq(campo_consultar3, valor_consultar3));
            lista = cri.list();

        } catch (Exception e) {
        } finally {
            session.close();
            return lista;
        }//fim finally
    }

    public List consultarQuatroItens(String campo_consultar1, String campo_consultar2, String campo_consultar3, String campo_consultar4,
            Object valor_consultar1, Object valor_consultar2, Object valor_consultar3, Object valor_consultar4) throws Exception {
        List lista = null;
        try {

            this.session = HibernateUtil.getInstance();
            Criteria cri = session.createCriteria(this.classe);
            cri.add(Restrictions.eq(campo_consultar1, valor_consultar1));
            cri.add(Restrictions.eq(campo_consultar2, valor_consultar2));
            cri.add(Restrictions.eq(campo_consultar3, valor_consultar3));
            cri.add(Restrictions.eq(campo_consultar4, valor_consultar4));
            lista = cri.list();

        } catch (Exception e) {
        } finally {
            session.close();
            return lista;
        }//fim finally
    }

    public List consultarDoisItensData(String campo_consultar1, String campo_consultar2,
            Object valor_consultar1, Object valor_consultar2) throws Exception {
        List lista = null;
        try {
            this.session = HibernateUtil.getInstance();
            Criteria cri = session.createCriteria(this.classe);
            cri.add(Restrictions.eq(campo_consultar1, valor_consultar1));
            cri.add(Restrictions.eq(campo_consultar2, valor_consultar2));
            lista = cri.list();
        } catch (Exception e) {
        } finally {
            session.close(); //nao se sabe porque não retorna se for fechado a sessão
            return lista;
        }//fim finally
    }

    public List consultarIncremental(String campoConsultar, String valorConsultar) throws Exception {

        List lista = null;

        try {

            this.session = HibernateUtil.getInstance();
            Criteria cri = session.createCriteria(this.classe);
            cri.add(Restrictions.ilike(campoConsultar, valorConsultar, MatchMode.START));
            cri.addOrder(Order.asc(campoConsultar));
            lista = cri.list();

        } catch (Exception e) {

            e.printStackTrace();
            throw new Exception(e.getMessage());

        } finally {

            session.close();
            return lista;

        }//fim finally
    }

    public List consultarIncremental(String campoConsultar1, String valorConsultar1,
            String campoConsultar2, String valorConsultar2) throws Exception {

        List lista = null;

        try {

            this.session = HibernateUtil.getInstance();
            Criteria cri = session.createCriteria(this.classe);

            cri.add(Restrictions.ilike(campoConsultar1, valorConsultar1));
            cri.add(Restrictions.ilike(campoConsultar1, valorConsultar1 + "%", MatchMode.ANYWHERE));
            cri.addOrder(Order.asc(campoConsultar2));
            lista = cri.list();

        } catch (Exception e) {

            e.printStackTrace();
            throw new Exception(e.getMessage());

        } finally {

            session.close();
            return lista;

        }//fim finally
    }
}

 